import base64

import grok
from cbu.pyhod.session import start_session
from cbu.pyhod.files import add_input_file, get_file
from cbu.pyhod.jobs import add_job, get_job_status
from js.jquery import jquery
from zope.component import getUtility

from LCAClassifier.web import resource
from LCAClassifier.web.interfaces import ILCAClassifyJob
from LCAClassifier.web.interfaces import IMyMailer


class LCAClassifyJob(grok.Model):
    grok.implements(ILCAClassifyJob)

    def __init__(self, fasta_files, db_name, bitscore, minscore, email=None):
        super(LCAClassifyJob, self).__init__()
        self.all_fasta = 'All.fasta'
        self.input_file_names = fasta_files.keys()
        self.session_id = start_session()
        blast_job_ids, xml_files = self._megablast(fasta_files, db_name)
        self.jobid = self._classify(blast_job_ids, xml_files,
                                    bitscore, minscore,db_name)
        self.email = email
        self.email_sent = False

    @property
    def status(self):
        return get_job_status(self.jobid)

    def _megablast(self, fasta_files, db_name):
        """MEGABLAST job submission."""
        blast_job_ids = []
        xml_files = []
        add_input_file(self.session_id, self.all_fasta,
                       '\n'.join(fasta_files.values()))

        for fasta_file_name in fasta_files.keys():
            xml_file_name = '.'.join(fasta_file_name.split('.')[:-1]) + ".xml"
            xml_files.append(xml_file_name)
            add_input_file(self.session_id, fasta_file_name,
                           fasta_files[fasta_file_name])
            parameters = ("-i %s -o %s -m7 -b100 -v100 -d %s -a 2" %
                          (fasta_file_name, xml_file_name, db_name))
            job_id = add_job(self.session_id, "lca_megablast", parameters,
                             [fasta_file_name], [xml_file_name], [], True)
            blast_job_ids.append(job_id)

        return blast_job_ids, xml_files

    def _classify(self, blast_job_ids, xml_files, bitscore=2, minscore=155, db_name="silvamod"):
        """Classify job submission."""
        args = ("-v -o -a -i %s -s %s -r %s -d %s %s" %
                (self.all_fasta, minscore, bitscore, db_name, ' '.join(xml_files)))
        in_files = xml_files + [self.all_fasta]
        out_files = ["All_Composition.txt"]
        for xml_file in xml_files:
            assignedFastaOut = xml_file.replace(".xml", "_Assignments.fasta")
            out_files.append(assignedFastaOut)
            compoOut = xml_file.replace(".xml", "_Composition.txt")
            out_files.append(compoOut)

        classify_job_id = add_job(session_id=self.session_id,
                                  executable_name="lca_classify",
                                  parameters=args,
                                  prerequisite_job_ids=blast_job_ids,
                                  input_file_names=in_files,
                                  output_file_names=out_files,
                                  stage_output_files=True)
        return classify_job_id


class Index(grok.View):

    def update(self):
        resource.style.need()
        jquery.need()
        #resource.result.need()
        resource.pagereload.need()

    def filenames(self):
        for filename in self.context.input_file_names:
            yield '.'.join(filename.split('.')[:-1])

    def result(self):
        if (self.context.status != 'FINISHED' and
            self.context.status != 'ERROR' and
            self.context.status != 'ABORTED'):
            loader = self.static['ajax-loader.gif']
            return ('<p>Your job is running...</p>\n'
                    '<p><img src="%s" />\n' % loader())

        if self.context.status == 'ERROR':
            return self._report_error('produced an error')

        if self.context.status == 'ABORTED':
            return self._report_error('was aborted')

        results = ('<table>\n<thead>\n<tr>\n'
                   '<th></th>\n<th>File name</th>\n'
                   '</tr>\n</thead>\n<tbody>\n')
        for filename in self.context.input_file_names:
            filename = '.'.join(filename.split('.')[:-1])
            result = ('<tr class="row-a"><td></td>'
                      '<td>\n'
                      '    <a href="./download?output_name=%s'
                      '&output_type=Assignments.fasta">\n'
                      '        %s_Assignments.fasta\n'
                      '    </a>\n'
                      '</td></tr>'
                      '<tr class="row-b"><td></td>'
                      '<td>\n'
                      '    <a href="./download?output_name=%s'
                      '&output_type=Composition.txt">\n'
                      '        %s_Composition.txt\n'
                      '    </a>\n'
                      '</td></tr>' % (filename, filename, filename, filename))
            results += result

        result = ('<tr class="row-a"><td></td>'
                  '<td>\n'
                  '    <a href="./download?output_name=All'
                  '&output_type=Composition.txt">\n'
                  '        All_Composition.txt\n'
                  '    </a>\n'
                  '</td>\n</tr>\n</tbody>\n</table>')
        results += result

        mailer = getUtility(IMyMailer)
        if self.context.email is not None:
            if not self.context.email_sent:
                url = grok.url(self.request, self.context)
                mailer.send_mail(self.context.email, 'Job finished', url)
                self.context.email_sent = True

        return results

    def _report_error(self, status):
        message = ("<p>Your job %s. Please contact the service group, "
                   "services@cbu.uib.no, and provide the following "
                   "job id: %s</p>" % (status, self.context.jobid))
        return message


class Status(grok.View):

    def render(self):
        return self.context.status


class Result(grok.View):

    def render(self):
        if (self.context.status != 'FINISHED' and
            self.context.status != 'ERROR' and
            self.context.status != 'ABORTED'):
            loader = self.static['ajax-loader.gif']
            return ('<p>Your job is running...</p>\n'
                    '<p><img src="%s" />\n' % loader())

        if self.context.status == 'ERROR':
            return self._report_error('produced an error')

        if self.context.status == 'ABORTED':
            return self._report_error('was aborted')

        results = ('<table>\n<thead>\n<tr>\n'
                   '<th></th>\n<th>File name</th>\n'
                   '</tr>\n</thead>\n<tbody>\n')
        for filename in self.context.input_file_names:
            filename = '.'.join(filename.split('.')[:-1])
            result = ('<tr class="row-a"><td></td>'
                      '<td>\n'
                      '    <a href="./download?output_name=%s'
                      '&output_type=Assignments.fasta">\n'
                      '        %s_Assignments.fasta\n'
                      '    </a>\n'
                      '</td></tr>'
                      '<tr class="row-b"><td></td>'
                      '<td>\n'
                      '    <a href="./download?output_name=%s'
                      '&output_type=Composition.txt">\n'
                      '        %s_Composition.txt\n'
                      '    </a>\n'
                      '</td></tr>' % (filename, filename, filename, filename))
            results += result

        result = ('<tr class="row-a"><td></td>'
                  '<td>\n'
                  '    <a href="./download?output_name=All'
                  '&output_type=Composition.txt">\n'
                  '        All_Composition.txt.fasta\n'
                  '    </a>\n'
                  '</td>\n</tr>\n</tbody>\n</table>')
        results += result

        mailer = getUtility(IMyMailer)
        if self.context.email is not None:
            if not self.context.email_sent:
                url = grok.url(self.request, self.context)
                mailer.send_mail(self.context.email, 'Job finished', url)
                self.context.email_sent = True

        return results

    def _report_error(self, status):
        message = ("<p>Your job %s. Please contact the service group, "
                   "services@cbu.uib.no, and provide the following "
                   "job id: %s</p>" % (status, self.context.jobid))
        return message


class Download(grok.View):

    def render(self):
        output_name = self.request['output_name']
        output_type = self.request['output_type']
        filename = '%s_%s' % (output_name, output_type)
        results = base64.b64decode(get_file(self.context.session_id, filename))
        self.request.response.setHeader(
            'Content-Disposition',
            'attachment; filename="%s"' % filename)
        self.request.response.setHeader('Content-Type',
                                        'application/text')
        return results


class DownloadAll(grok.view):

    def render(self):
        return 'Not implemented'
